#include <stdio.h>
#include <string.h>
#include "cmd_decl.h"
#include "cmd_test.h"
#include "tm1638_enevt.h"
#include "TM1638.h"
#include "esp_http_client_example.c"


/*
static void register_***();   命令注册声明
在命令组注册函数添加命令注册
命令参数结构体构造
命令处理函数
命令注册绑定函数

 */

static struct {
	struct arg_str *name;		//-n task name
	struct arg_end *end;
} task_arg;




//私有函数
void task_random(void *pvParameter){
    uint32_t tem=0;
    while(1){
        vTaskDelay(1000 / portTICK_PERIOD_MS);
        //等待通知，接收前不处理，接收完自动清零    
        if(xTaskNotifyWait(0,ULONG_MAX,&tem,portMAX_DELAY)){

            printf("task name: %s\trandom:%u\n",pcTaskGetTaskName(NULL),tem);
        
        }
    
    }
}

void task_bit(void *pvParameter){
        uint32_t tem=0;
        printf("task name: %s\t",pcTaskGetTaskName(NULL));
        while(1){
            vTaskDelay(1000 / portTICK_PERIOD_MS);
        //等待通知，接收前不处理，接收完自动清零    
            if(xTaskNotifyWait(0,ULONG_MAX,&tem,portMAX_DELAY)){
                printf("uint32:%u\n",tem);
                    for(int i=0;i<32;i++){
                        if(tem & (1UL<<i))printf("%02u\t",i);
                    }
                printf("\n");
            }
            
        }

    }

void task_add(void *pvParameter){
        uint32_t tem=0; 
        printf("task name: %s\t",pcTaskGetTaskName(NULL));
        while(1){
        //等待通知，增量  +1
            vTaskDelay(1000 / portTICK_PERIOD_MS);
            if(ulTaskNotifyTake(pdFALSE,portMAX_DELAY)){
                printf("uint32:%u\n",tem);
            } 

            //与上面等价，不过可以取出通知的值
            if(xTaskNotifyWait(0,0,&tem,portMAX_DELAY)){
                printf("通知值:%u\n",tem);
        }
                   
        
        }
    }

void task_on_off(void *pvParameter){
    uint32_t tem=0; 
    printf("task name: %s\t",pcTaskGetTaskName(NULL));
    while(1){
        vTaskDelay(1000 / portTICK_PERIOD_MS); 
        //等待通知，增量-1    
        if(ulTaskNotifyTake(pdTRUE,portMAX_DELAY)){
            printf("uint32:%u\n",tem);
        } 
        //与上面等价，不过可以取出通知的值
        if(xTaskNotifyWait(0,ULONG_MAX,&tem,portMAX_DELAY)){
            printf("通知值:%u\n",tem);
        }
              
        
    }

}

static portTickType xLastWakeTime;  
const portTickType xFrequency = 1000;

static void test_task(void *pvParameter)
{

 /*   // freertos task
    uint32_t n=0; 
    while(1) {
        //vTaskDelay(1000 / portTICK_PERIOD_MS);
        if(n%10 == 1){
			printf("task 参数：%s\t",(u_char *)pvParameter);
            printf("task name: %s\t",pcTaskGetTaskName(NULL));
			printf("task 任务 计数 %0d\n",n);
			}
        n++;
        vTaskDelay(1000 / portTICK_PERIOD_MS);
    }
*/
    TaskHandle_t    bit;
    TaskHandle_t    random;
    TaskHandle_t    add;
    TaskHandle_t    on_off;

    printf("task name: %s\tesp-idf:%s\n",pcTaskGetTaskName(NULL),esp_get_idf_version());

    xTaskCreatePinnedToCore(&task_random, "random", 2048, NULL, 3,&random,1);
    printf("random 任务创建\n");

    xTaskCreate(&task_bit, "bit", 2048, NULL, 4,&bit);
    printf("bit 任务创建\n");
        
    xTaskCreate(&task_add, "add", 2048, NULL, 3,&add);
    printf("add 任务创建！！！\n");
        
    xTaskCreate(&task_on_off, "on_off", 2048, NULL, 4,&on_off);
    printf("on_off 任务创建！！！\n");

    xLastWakeTime = xTaskGetTickCount(); 

    while(1){
        //向random句柄发送可直接覆盖的u32随机数
        printf("main 向random 发送随机数\n");
        xTaskNotify(random,esp_random(),eSetValueWithOverwrite);
        vTaskDelayUntil( &xLastWakeTime,xFrequency ); 
        //向bit句柄发送u32随机数bit
        printf("main 向bit 发送随机数\n");
        xTaskNotify(bit,esp_random(),eSetBits);
        vTaskDelayUntil( &xLastWakeTime,xFrequency ); 
        //向add句柄发增量1
        printf("main 向add 发送增量1\n");
        xTaskNotifyGive(add);
        vTaskDelayUntil( &xLastWakeTime,xFrequency ); 
        //向on_off句柄发送增量1
        printf("main 向on_off 发送开关\n");
        xTaskNotifyGive(on_off);
        vTaskDelayUntil( &xLastWakeTime,xFrequency );  
    }
}


void test2_task(void *pvParameter)
{
    u_char num[8];		//各个数码管显示的值
    u_char key=8;
    tm1638_drive *drive_tm1638=tm1638_drive_malloc(NULL);	
    printf("tm1638_drive %p\n",drive_tm1638);
/* 	 for(uint8_t i=0;i<8;i++){
        //Write_DATA(i<<1,SMg);
        //tm1638_drive_num_input(drive_tm1638,i,SMg); //初始化寄存器
        tm1638_drive_led_up(drive_tm1638,i);
        }   */

    for(uint8_t i=0;i<8;i++){
            tm1638_drive_led_up(drive_tm1638,i);
            vTaskDelay(100 / portTICK_PERIOD_MS);
        }
        vTaskDelay(1000 / portTICK_PERIOD_MS);
    for(uint8_t i=8;i>0;i--){
            tm1638_drive_led_off(drive_tm1638,i-1);
            vTaskDelay(100 / portTICK_PERIOD_MS);
        }   

	printf("开始测试\n");
    tm1638_drive_num_input(drive_tm1638,0,'/x0f');
    tm1638_drive_num_input(drive_tm1638,1,'/x08');
    tm1638_drive_num_input(drive_tm1638,2,'/x06');
    while(1)
	{   
		//读按键值
        key=tm1638_drive_key_get(drive_tm1638);
        if(key<8)
		{   
            printf("按键%1u\n",key);
			num[key]++;
			while(tm1638_drive_key_get(drive_tm1638)==key);		       //等待按键释放
			if(num[key]>15)
			num[key]=0;
			//Write_DATA(key,tab[num[key]]);
            tm1638_drive_num_input(drive_tm1638,key,tab[num[key]]);
			tm1638_drive_led_up(drive_tm1638,key);
            vTaskDelay(1000 / portTICK_PERIOD_MS);
            tm1638_drive_led_off(drive_tm1638,key);
		} 
        vTaskDelay(1000 / portTICK_PERIOD_MS);
	}
}

//命令处理函数
static int cmd_test(int argc, char** argv){
	//初始化变量
	//参数格式化
    TaskHandle_t tem=NULL;
	int nerrors = arg_parse(argc, argv, (void**) &task_arg);
    if (nerrors != 0) {
        arg_print_errors(stderr, task_arg.end, argv[0]);
        return 1;
    }
	if(task_arg.name->count) printf("参数值：%s\n",task_arg.name->sval[0]);
    if(strcmp(task_arg.name->sval[0],"tm1638") == 0){
        xTaskCreatePinnedToCore(&test2_task, task_arg.name->sval[0], 8000, (void *)task_arg.name->sval[0], 5,&tem,1);
        printf("创建tm1638任务\n");
        return 0;
    }
	
    if(strcmp(task_arg.name->sval[0],"http") == 0){
        xTaskCreate(&http_test_task, task_arg.name->sval[0], 9192, NULL, 5, NULL);
        //xTaskCreatePinnedToCore(&test2_task, , 5000, (void *)task_arg.name->sval[0], 5,&tem,1);
        printf("创建%s任务\n",task_arg.name->sval[0]);
        return 0;
    }
    

	if(xTaskCreatePinnedToCore(&test_task, task_arg.name->sval[0], 2048, (void *)task_arg.name->sval[0], 5,&tem,1)){
        return 0;
    }
    else{
        printf("任务创建出错！！！\n");
        return 1;
    }
    
}



//命令注册函数
void register_test_task(void){
	//参数表格式化
    task_arg.name = arg_str1(NULL,NULL, "<str>", "task名字.");
    task_arg.end = arg_end(1);
	//命令注册
	const esp_console_cmd_t cmd = {
        .command = "test",
        .help = "test task",
        .hint = "name",
        .func = &cmd_test,
        .argtable = &task_arg
    };
    ESP_ERROR_CHECK( esp_console_cmd_register(&cmd) );
}